import charts.models as models
import charts.funcs as funcs
import cv2
import numpy as np


class Chart:
    def __init__(self, y, step=1, rad=100, iters=0, name='out.png',
                 color=models.Color(255, 255, 255), background=models.Color(0, 0, 0),
                 lines=models.Color(0, 255, 0), backward=True):
        self.y_func = y
        self.step = step
        self.rad = rad
        self.rad2 = int(rad/2)
        self.x = 0
        self.y = 0
        self.iters = iters
        if self.iters == 0:
            self.iters = self.rad2
        self.matrix = [[]]
        self.name = name
        self.model = models.Matrix
        self.color = color
        self.background = background
        self.lines = lines
        self.backward = backward

    def iter(self):
        try:
            x = self.x + self.step
            y = self.y_func(self.x)
            if not x > self.rad2:
                if not y > self.rad2:
                    self.x = x
                    self.y = y
        except Exception as e:
            print(e)

    def generate_lines(self):
        w = self.rad2
        for i in range(self.rad):
            self.matrix[w][i] = 2
            self.matrix[i][w] = 2

    def generate_matrix(self):
        self.matrix = [[0 for i1 in range(self.rad)] for i0 in range(self.rad)]
        self.generate_lines()

    def to_axis(self):
        x = round((self.rad2+self.x))
        y = round((self.rad2-self.y))
        return x, y

    def generate_chart(self):
        self.generate_matrix()
        for i in range(self.iters):
            self.iter()
            axis = self.to_axis()
            try:
                self.matrix[axis[1]][axis[0]] = 1
            except:
                pass
        if self.backward:
            self.step *= -1
            self.x = 0
            for i in range(self.iters):
                self.iter()
                axis = self.to_axis()
                try:
                    self.matrix[axis[1]][axis[0]] = 1
                except:
                    pass
        return self.matrix

    def chart_to_model(self):
        m = models.Matrix(self.rad, self.rad)
        for line in range(len(self.matrix)):
            l = self.matrix[line]
            for char in range(len(l)):
                c = l[char]
                if c == 1:
                    m[line][char] = self.color
                elif c == 0:
                    m[line][char] = self.background
                elif c == 2:
                    m[line][char] = self.lines
        self.model = np.float32(m.to_img())

    def model_to_img(self):
        img_cv = cv2.resize(cv2.UMat(self.model), (self.rad, self.rad))
        cv2.imwrite(self.name, img_cv)

    def generate(self):
        self.generate_chart()
        self.chart_to_model()
        self.model_to_img()
